// This package impliments general data for the entire app.
package data

import (
	"bytes"
	"strings"
	"unicode/utf8"
)

const AWWWEAttributePrefix string = "x-awwwe-browser-"

var (
	AWWWEParamActualURL string = AWWWEAttributePrefix + "url"
	AWWWE               string = "awwwe"
)

var (
	AWWWEAttributeTemp      string = AWWWEAttributePrefix + "temp"
	AWWWEAttributeId        string = AWWWEAttributePrefix + "id"
	AWWWEAttributeTagName   string = AWWWEAttributePrefix + "tagname"
	AWWWEAttributeTagPrefix string = AWWWEAttributePrefix + "tagprefix"
	AWWWEAttributeVoice     string = AWWWEAttributePrefix + "vxml"
)

const (
	DefaultNSUrl       string = "http://www.w3.org/1999/xhtml"
	FakeNSUrl          string = "http://www.w3.org/1999/xhtml/fake"
	FakeAttributeName  string = "x-fakeAttName"
	FakeAttributeValue string = "fakeAttValue"
	FakeNS             string = "fake"
)

const (
	EmptyString                     string = ""
	SpaceString                     string = " "
	WhiteSpaceString                string = " \r\n\t"
	NewLineString                   string = "\n"
	ColonString                     string = ":"
	CommaString                     string = ","
	PeriodString                    string = "."
	DQuoteString                    string = "\""
	SQuoteString                    string = "'"
	EqualString                     string = "="
	LeftSquareBracketString         string = "["
	RightSquareBracketString        string = "]"
	CommentStartString              string = "<!--"
	CommentEndString                string = "-->"
	ConditionalCommentStartString   string = "<!--[if"
	ConditionalCommentEndString     string = "<![endif]-->"
	CDataStartString                string = "<![CDATA["
	CDataEndString                  string = "]]>"
	DirectiveStartString            string = "<?"
	DirectiveEndString              string = ">"
	ProcessorInstructionStartString string = "<!"
	ProcessorInstructionEndString   string = "!>"
	DocTypeStartString              string = "<!DOCTYPE"
	DocTypeStartStringLower         string = "<!doctype"
	DocTypeEndString                string = ">"
	TagStartString                  string = "<"
	TagEndString                    string = ">"
	TagSlashString                  string = "/"
	GreaterThanString               string = ">"
	GreaterThanCharRefString        string = "&gt;"
	LessThanString                  string = "<"
	LessThanCharRefString           string = "&lt;"
	AmpersandString                 string = "&"
	AmpersandCharRefString          string = "&amp;"
	DQuoteCharRefString             string = "&quot;"
	LeftParenString                 string = "("
	RightParenString                string = ")"
	VXMLLongPauseString             string = "<break time=\"2s\">"
	VXMLShortPauseString            string = "<break time=\"1s\">"
)

var (
	EmptyBytes                     []byte = []byte{}
	SpaceBytes                     []byte = []byte(SpaceString)
	NewLineBytes                   []byte = []byte(NewLineString)
	ColonBytes                     []byte = []byte(ColonString)
	CommaBytes                     []byte = []byte(PeriodString)
	PeriodBytes                    []byte = []byte(ColonString)
	DQuoteBytes                    []byte = []byte(DQuoteString)
	SQuoteBytes                    []byte = []byte(SQuoteString)
	EqualBytes                     []byte = []byte(EqualString)
	LeftSquareBracketBytes         []byte = []byte(LeftSquareBracketString)
	RightSquareBracketBytes        []byte = []byte(RightSquareBracketString)
	CommentStartBytes              []byte = []byte(CommentStartString)
	CommentEndBytes                []byte = []byte(CommentEndString)
	ConditionalCommentStartBytes   []byte = []byte(ConditionalCommentStartString)
	ConditionalCommentEndBytes     []byte = []byte(ConditionalCommentEndString)
	CDataStartBytes                []byte = []byte(CDataStartString)
	CDataEndBytes                  []byte = []byte(CDataEndString)
	DirectiveStartBytes            []byte = []byte(DirectiveStartString)
	DirectiveEndBytes              []byte = []byte(DirectiveEndString)
	ProcessorInstructionStartBytes []byte = []byte(ProcessorInstructionStartString)
	ProcessorInstructionEndBytes   []byte = []byte(ProcessorInstructionEndString)
	DocTypeStartBytes              []byte = []byte(DocTypeStartString)
	DocTypeStartBytesLower         []byte = []byte(DocTypeStartStringLower)
	DocTypeEndBytes                []byte = []byte(DocTypeEndString)
	TagStartBytes                  []byte = []byte(TagStartString)
	TagEndBytes                    []byte = []byte(TagEndString)
	TagSlashBytes                  []byte = []byte(TagSlashString)
	GreaterThanBytes               []byte = []byte(GreaterThanString)
	GreaterThanCharRefBytes        []byte = []byte(GreaterThanCharRefString)
	LessThanBytes                  []byte = []byte(LessThanString)
	LessThanCharRefBytes           []byte = []byte(LessThanCharRefString)
	AmpersandBytes                 []byte = []byte(AmpersandString)
	AmpersandCharRefBytes          []byte = []byte(AmpersandCharRefString)
	LeftParenBytes                 []byte = []byte(LeftParenString)
	RightParenBytes                []byte = []byte(RightParenString)
	VXMLLongPauseBytes             []byte = []byte(VXMLLongPauseString)
	VXMLShortPauseBytes            []byte = []byte(VXMLShortPauseString)
)

var (
	SpaceRune              rune   = bytes.Runes([]byte(SpaceBytes))[0]
	NewLineRune            rune   = bytes.Runes([]byte(NewLineBytes))[0]
	EqualsRune             rune   = bytes.Runes([]byte(EqualBytes))[0]
	SQuoteRune             rune   = bytes.Runes([]byte(SQuoteBytes))[0]
	DQuoteRune             rune   = bytes.Runes([]byte(DQuoteBytes))[0]
	ColonRune              rune   = bytes.Runes([]byte(ColonBytes))[0]
	LeftSquareBracketRune  rune   = bytes.Runes([]byte(LeftSquareBracketBytes))[0]
	RightSquareBracketRune rune   = bytes.Runes([]byte(RightSquareBracketBytes))[0]
	EmptyRunes             []rune = make([]rune, 0, 0)
	LeftParenRune          rune   = bytes.Runes([]byte(LeftParenBytes))[0]
	RightParenRune         rune   = bytes.Runes([]byte(RightParenBytes))[0]
)

const (
	VXMLLongPause  string = "<lp>"
	VXMLShortPause string = "<sp>"
)

// Converts bytes to a string.
// Param bb is the bytes to be converted.
func BytesToUTF8String(bb []byte) string {
	bfr := bytes.NewBuffer(bb)
	return bfr.String()
}

// Converts bytes to a string with the white space trimmed off the beginning and end of the string.
// Param bb is the bytes to be converted.
func BytesToUTF8StringTrim(bb []byte) string {
	var s string
	s = BytesToUTF8String(bb)
	return strings.Trim(s, WhiteSpaceString)
}

// Converts runes to a string.
// Param rr is the runes to be converted.
func RunesToUTF8String(rr []rune) string {
	bb := make([]byte, (len(rr) * utf8.UTFMax))
	var length int = 0
	for _, r := range rr {
		l := utf8.EncodeRune(bb[length:], r)
		length += l
	}
	bfr := bytes.NewBuffer(bb[:length])
	return bfr.String()
}

// Converts runes to a slice of bytes.
// Param rr is the runes to be converted.
func RunesToUTF8Bytes(rr []rune) []byte {
	bb := make([]byte, (len(rr) * utf8.UTFMax))
	var length int = 0
	for _, r := range rr {
		l := utf8.EncodeRune(bb[length:], r)
		length += l
	}
	bfr := bytes.NewBuffer(bb[:length])
	return bfr.Bytes()
}

func HexStringToInt(s string) (int, bool) {
	var v int
	var r rune
	var ls string
	var ok bool
	v = 0
	ls = strings.ToLower(s)
	ok = false
	for _, r = range ls {
		if r >= '0' && r <= '9' {
			v *= 16
			v += int(r) - '0'
			ok = true
		} else {
			if r >= 'a' && r <= 'f' {
				v *= 16
				v += int(r) - 'a' + 10
				ok = true
			}
		}
	}
	return v, ok
}

func StringToInt(s string) (int, bool) {
	var v, i int
	var sign, r rune
	var ok bool
	v = 0
	sign = '+'
	ok = false
	for i, r = range s {
		if i == 0 && r == '-' {
			sign = r
		} else if r >= '0' && r <= '9' {
			v *= 10
			v += int(r) - '0'
			ok = true
		}
	}
	if sign == '-' {
		v *= -1
	}
	return v, ok
}

func oldStringToInt(s string) (int, bool) {
	bfr := bytes.NewBufferString(strings.Trim(s, WhiteSpaceString))
	runes := bytes.Runes(bfr.Bytes())
	v := 0
	sign := '+'
	ok := false
	for i, r := range runes {
		if i == 0 && r == '-' {
			sign = r
		} else if r >= '0' && r <= '9' {
			v *= 10
			v += int(r) - '0'
			ok = true
		}
	}
	if sign == '-' {
		v *= -1
	}
	return v, ok
}
